package com.ruoyi.washer.common;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.washer.domain.XwPurchaseOrder;
import com.ruoyi.washer.mapper.XwDeviceMapper;
import com.ruoyi.washer.mapper.XwProductMapper;
import com.ruoyi.washer.mapper.XwPurchaseOrderMapper;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

@Service
public class PaymentRefundServiceImpl {
    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String secret;

    @Value("${wx.mch_id}")
    private String mchId;

    @Value("${wx.key_v2}")
    private String key_v2;

    @Value("${wx.key_v3}")
    private String key_v3;

    @Value("${wx.notify_url}")
    private String notify_url;

    @Value("${wx.refund_notify_url}")
    private String refund_notify_url;

    @Value("${wx.private_key}")
    private String private_key;

    @Value("${wx.mch_serial_no}")
    private String mch_serial_no;

    private static final Logger logger = LoggerFactory.getLogger(PaymentRefundServiceImpl.class);



    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private XwDeviceMapper xwDeviceMapper;

    @Autowired
    private XwProductMapper xwProductMapper;

    @Autowired
    private XwPurchaseOrderMapper xwPurchaseOrderMapper;

    @Autowired
    private SysConfigMapper sysConfigMapper;


    /*发起退款*/
    public String createRefundOrder(String outTradeNo, int total, int refund) {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            String outRefundNo = "refund"+outTradeNo;
            rootNode.put("out_refund_no", outRefundNo)
                    .put("notify_url", refund_notify_url)
                    .put("out_trade_no", outTradeNo);
            rootNode.putObject("amount")
                    .put("total", total)
                    .put("refund", refund)
                    .put("currency", "CNY");
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

        /*
退款回调
{
	"mchid": "1514057421",
	"out_trade_no": "036ac541383646aefe97943512c1062b",
	"transaction_id": "4200002038202311012558514008",
	"out_refund_no": "849fe769f45e2848424c42106ed09556",
	"refund_id": "50302407442023110129733837763",
	"refund_status": "SUCCESS",
	"success_time": "2023-11-01T17:26:26+08:00",
	"amount": {
		"total": 1,
		"refund": 1,
		"payer_total": 1,
		"payer_refund": 1
	},
	"user_received_account": "支付用户零钱"
}
 */

    public void refundNotifyAll(HttpServletRequest request)throws Exception{
        String encryptedBody=getBody(request);
        String decryptedBody=decryptOrder(encryptedBody);
        JSONObject jsonObject=JSONObject.parseObject(decryptedBody);
        logger.error("Refund-jsonObject============="+jsonObject);
        String refundStatus=jsonObject.getString("refund_status");
        String outTradeNo=jsonObject.getString("out_trade_no");
        logger.error("Refund-jsonObject1============="+refundStatus.equals("SUCCESS"));
        if(refundStatus.equals("SUCCESS")){
            XwPurchaseOrder xwPurchaseOrder=xwPurchaseOrderMapper.selectXwPurchaseOrderByOutTradeNo(outTradeNo);
            int payerRefund=jsonObject.getJSONObject("amount").getInteger("payer_refund");
            BigDecimal decimal = new BigDecimal(""+payerRefund);
            xwPurchaseOrder.setRefundState("3");
            xwPurchaseOrder.setRefundAmountReal(decimal);
            xwPurchaseOrderMapper.updateXwPurchaseOrder(xwPurchaseOrder);
        }
    }

    /*
   获取body
    */
    public String getBody(HttpServletRequest request)throws Exception{
        String body="";
        BufferedReader reader=null;
        try {
            reader = request.getReader();
            String line;
            StringBuilder inputString = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            body = inputString.toString();
            reader.close();
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            if(reader!=null){
                reader.close();
                reader=null;
            }
        }
        return body;
    }
    /*支付通知和退款通知给服务器的回调 解密报文*/
    public String decryptOrder(String body) {
        try {
            AesUtil util = new AesUtil(key_v3.getBytes(StandardCharsets.UTF_8));
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode node = objectMapper.readTree(body);
            JsonNode resource = node.get("resource");
            String ciphertext = resource.get("ciphertext").textValue();
            String associatedData = resource.get("associated_data").textValue();
            String nonce = resource.get("nonce").textValue();
            return util.decryptToString(associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
